package com.hzit.thread;

import com.hzit.order.HzitOrderApplication;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.math.BigDecimal;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 类名：
 * 作者：WF
 * 功能：
 */
@SpringBootTest(classes = HzitOrderApplication.class)
public class ThreadPoolDemo {
	@Autowired
	private ThreadPoolExecutor executor;
	//1. 创建线程池

	/**
	 * public ThreadPoolExecutor(int corePoolSize,
	 *                               int maximumPoolSize,
	 *                               long keepAliveTime,
	 *                               TimeUnit unit,
	 *                               BlockingQueue<Runnable> workQueue,
	 *                               ThreadFactory threadFactory,
	 *                               RejectedExecutionHandler handler)
	 */
	@Test
	public void test01(){
		//1.1 创建线程池的第一种方案(一般不用，因为默认值可能不满足要求)
		ScheduledExecutorService executorService1 = Executors.newScheduledThreadPool(5);
		ThreadPoolExecutor executor = new ThreadPoolExecutor(5,20,10,
										TimeUnit.SECONDS,
										new LinkedBlockingDeque<>(),
										Executors.defaultThreadFactory(),
										new ThreadPoolExecutor.AbortPolicy()
				);

	}
	//3. 使用异步编排技术创建异步对象
	@Test
	public void test02() throws ExecutionException, InterruptedException {
		//第一阶段：得到异步对象
		//3.1 实现Runnable接口方式创建异步对象
		CompletableFuture<Void> future01 = CompletableFuture.runAsync(() -> {
			System.out.println("第一个任务执行！");
		}, executor);
		//3.2 实现Supplier接口方式创建异步对象 (有返回值)
		CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(() -> {
			int a = 10 / 2;
			System.out.println("第二个任务执行！");
			return 10;
		}, executor);
		// Integer rs = future02.get();
		// System.out.println("rs = " + rs);

		//第二阶段：
		//2.1 上一阶段完成后的回调 (得到上一个任务的值并同时处理异常)
		// CompletableFuture<Integer> future03 = future02.whenCompleteAsync((r, t) -> {
		// 	System.out.println("得到上个任务的值：" + r) ;
		// 	System.out.println("上个任务是否有异常：" + (t == null ? false : true));
		// 	System.out.println(t);
		// }, executor);
		// Integer rs2 = future03.get();
		// System.out.println("rs2 = " + rs2);
		//2.2 上一阶段完成后的回调 (专门处理异常)
		// CompletableFuture<Integer> future04 = future02.exceptionally(t -> {
		// 	String message = t.getMessage();
		// 	System.out.println("异常信息：" + message);
		// 	return 3;
		// });
		// Integer rs3 = future04.get();
		// System.out.println("rs3 = " + rs3);

		//第三部分：线程串行化方法
		//3.1 执行新任务时用的是Runnable接口
		CompletableFuture<Void> future03 = future01.thenRunAsync(new Runnable() {
			@Override
			public void run() {
				System.out.println("任务一执行完成后执行此任务！");
			}
		} , executor);
		//3.2 执行新任务时用的Function接口（有输入参数和返回值）
		CompletableFuture<Integer> future04 = future02.thenApplyAsync(new Function<Integer, Integer>() {
			@Override
			public Integer apply(Integer a) {
				return a + 1;
			}
		});
		// System.out.println("future04结果 = " + future04.get());
		//3.3 执行新任务时用的Consumer接口（只有输入参数无输出参数）
		// CompletableFuture<Void> future05 = future02.thenAcceptAsync(new Consumer<Integer>() {
		// 	@Override
		// 	public void accept(Integer a) {
		// 		System.out.println("上次任务返回结果：" + a);
		// 	}
		// }, executor);

		// 第四阶段：组合多个任务
		//4.1 组合任务时有返回值 （可以有新的返回值）
		// CompletableFuture<Integer> future06 = future02.thenCombineAsync(future04, new BiFunction<Integer, Integer, Integer>() {
		// 	@Override
		// 	public Integer apply(Integer a, Integer b) {
		// 		System.out.println("任务二的值：" + a + ",任务四的值：" + b);
		// 		return a + b + 10;
		// 	}
		// }, executor);
		// Integer rs3 = future06.get();
		// System.out.println("rs3 = " + rs3);
		//4.2 组合任务时有返回值 （没有新的返回值）
		CompletableFuture<Void> future07 = future02.thenAcceptBothAsync(future04, new BiConsumer<Integer, Integer>() {
			@Override
			public void accept(Integer a, Integer b) {   // a,b分别代表任务future02与任务future04的返回值
				System.out.println("[future07]--> 任务二的值：" + a + ",任务四的值：" + b);
			}
		},executor);

		//第五阶段：所有任务都完成
		CompletableFuture<Void> future = CompletableFuture.allOf(future02, future04, future07);
		future.get();



	}
	@Test
	public  void test05() {
		BigDecimal bd = new BigDecimal(0.0);
		for (int i = 0; i < 10; i++) {
			bd = bd.add(new BigDecimal(10));
		}
		System.out.println("bd = " + bd.doubleValue());
	}

}
